#pragma once
#include<iostream>
#include<vector>
#include<string>

#include"../ThirdLibrary/mysql-connector-c-6.1.11-linux-glibc2.12-x86_64/include/mysql.h"
#include"common.hpp"
#include"../CommonComponent/Log.hpp"

    /*
        我们的数据库oj_database中只需要一张questions表，它包含如下字段：
        id:题目编号 --主键
        title:题目标题
        level:题目难度
        desc:题目描述
        timelimit:时间限制   --单位:秒(s)
        spacelimit:空间限制  --单位：千字节(kb)
        precode:预设代码
        testcode:测试代码
    */
namespace ns_module{

    std::string host="127.0.0.1";
    std::string user="ojcompile";
    std::string passwd="20241109MiMa@";
    std::string db="oj_database";
    std::string unix_socket="";
    unsigned int port=3306;
    unsigned int clientflag=0;

    //连接数据库
    class start{
    public:
        start(){
            _con=mysql_init(nullptr);
            if(nullptr==_con){
                Log(FATAL,"mysql init error\n");
            }
            else{  
                MYSQL* ret =mysql_real_connect(_con,host.c_str(),user.c_str(),passwd.c_str(),db.c_str(),port,unix_socket.c_str(),clientflag);
                if(nullptr==ret){
                    Log(FATAL,"mysql connect error:%s\n",mysql_error(_con));
                }
                else{
                    mysql_set_character_set(_con,"utf8mb4");
                    Log(INFO,"concect to mysql successfully\n");
                }
            }
        }

        MYSQL* GetConnect(){
            return _con;
        }

        ~start(){
            if(nullptr!=_con){
                mysql_close(_con);
            }
        }
    private:
        MYSQL* _con=nullptr;
    };

    start _s;
    
    //获取题目列表供客户浏览，包含字段：id title level
    bool GetQuestionList(std::vector<ns_mvccom::questionList>& lists){
        MYSQL* my=_s.GetConnect();
        if(nullptr==my){
            return false;
        }
        std::string command="select id,title,level from questions;";
        if(mysql_query(my,command.c_str())){
            std::string err=mysql_error(my);
            Log(ERROR,"select error: %s\n",err.c_str());
            return false;
        }
        MYSQL_RES* handle=mysql_store_result(my);
        if(nullptr==handle){
            Log(ERROR,"get mysql_store_result error");
            return false;
        }

        int row=mysql_num_rows(handle);
        int column=mysql_num_fields(handle);

        int i=0;
        for(i=0;i<row;++i){
            MYSQL_ROW line=mysql_fetch_row(handle);
            ns_mvccom::questionList t;
            t.id=std::stoi(line[0]);
            t.title=line[1];
            t.level=line[2];
            lists.push_back(t);
        }

        mysql_free_result(handle);
        return true;
    }

    //获取一个题目的详细信息信息，id title level desc precode
    bool GetQuestionDetail(std::string id,ns_mvccom::questionDetail& details){
        MYSQL* my=_s.GetConnect();
        if(nullptr==my){
            return false;
        }
        std::string command="select id,title,level,desc,precode from questions where id = ";
        command+=id;
        command+=";";
        if(mysql_query(my,command.c_str())){
            std::string err=mysql_error(my);
            Log(ERROR,"select error: %s\n",err.c_str());
            return false;
        }
        MYSQL_RES* handle=mysql_store_result(my);
        if(nullptr==handle){
            Log(ERROR,"get mysql_store_result error");
            return false;
        }

        MYSQL_ROW line=mysql_fetch_row(handle);
        details.id=std::stoi(line[0]);
        details.title=line[1];
        details.level=line[2];
        details.desc=line[3];
        details.precode=line[4];

        mysql_free_result(handle);
        return true;
    }

    //获取编译测试需要的信息 timelimit spacelimit testcode
    bool GetQuestionTest(std::string id,ns_mvccom::questionTest& test){
        MYSQL* my=_s.GetConnect();
        if(nullptr==my){
            return false;
        }
        std::string command="select timelimit,spacelimit,testcode from questions where id = ";
        command+=id;
        command+=";";
        if(mysql_query(my,command.c_str())){
            std::string err=mysql_error(my);
            Log(ERROR,"select error: %s\n",err.c_str());
            return false;
        }
        MYSQL_RES* handle=mysql_store_result(my);
        if(nullptr==handle){
            Log(ERROR,"get mysql_store_result error");
            return false;
        }

        MYSQL_ROW line=mysql_fetch_row(handle);
        test.timelimit=std::stoi(line[0]);
        test.spacelimit=std::stoi(line[1]);
        test.testcode=line[2];

        mysql_free_result(handle);
        return true;
    }
}